package com.qianxun.module.datasource1.develop.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qianxun.framework.common.util.AssertUtil;
import com.qianxun.framework.common.util.NumberCodeGenerator;
import com.qianxun.framework.common.util.ObjectUtil;
import com.qianxun.module.datasource1.develop.dto.SysFunctionRoleDTO;
import com.qianxun.module.datasource1.develop.entity.SysFunctionRole;
import com.qianxun.module.datasource1.develop.mapper.SysFunctionRoleMapper;
import com.qianxun.module.datasource1.develop.service.SysFunctionRoleRelationService;
import com.qianxun.module.datasource1.develop.service.SysFunctionRoleService;
import com.qianxun.module.datasource1.admin.service.SysUserFunctionRoleRelationService;
import com.qianxun.module.base.bo.ZTreeNode;
import com.qianxun.module.base.exception.ServiceInterruptionException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 *   服务实现类
 * </p>
 *
 * @author admin
 * @since 2019-11-27
 */
@Service
public class SysFunctionRoleServiceImpl extends ServiceImpl<SysFunctionRoleMapper, SysFunctionRole> implements SysFunctionRoleService {

    @Resource
    private SysFunctionRoleRelationService sysFunctionRoleRelationService;
    @Resource
    private SysUserFunctionRoleRelationService sysUserFunctionRoleRelationService;

    @Override
    public void add(SysFunctionRoleDTO query) {
        SysFunctionRole old = this.baseMapper.selectLastOneByName(query.getName());
        AssertUtil.isNull(old , ServiceInterruptionException.fail(400 ,query.getName().concat(" 名称已存在")));

        SysFunctionRole sysAdminFunctionRole = new SysFunctionRole();
        ObjectUtil.switchAllFieldValue(sysAdminFunctionRole, query);
        sysAdminFunctionRole.init();

        SysFunctionRole parent = selectOneByIdDescLimit1(query.getPid());
        if(parent == null && query.getPid() != 0){
            throw ServiceInterruptionException.fail(400 ,"上级角色不存在, pid：" + query.getPid());
        }

        String code = null;
        NumberCodeGenerator numberCodeGenerator = NumberCodeGenerator.build();
        if(sysAdminFunctionRole.getPid() == 0){
            SysFunctionRole lastBrother = selectOneByPidDescLimit1(0);
            try {
                code = numberCodeGenerator.next(lastBrother.getCode());
            } catch (Exception e) {
                throw ServiceInterruptionException.fail(500 ,"功能角色编码不可分配，请联系管理员");
            }
        }else{
            SysFunctionRole lastBrother = selectOneByPidDescLimit1(parent.getId());
            try {
                code = lastBrother == null ? numberCodeGenerator.child(parent.getCode()): numberCodeGenerator.next(lastBrother.getCode());
            } catch (Exception e) {
                throw ServiceInterruptionException.fail(500 ,"功能角色编码不可分配，请联系管理员");
            }
        }
        sysAdminFunctionRole.setCode(code);

        save(sysAdminFunctionRole);
    }

    @Override
    public void deleteSelfAndChildrenById(Integer id) {
        SysFunctionRole sysAdminFunctionRole = this.baseMapper.selectById(id);
        if(sysAdminFunctionRole == null){
            return;
        }
        //通过菜单编号查询所有节点
        String rootCode = NumberCodeGenerator.build().original(sysAdminFunctionRole.getCode());
        //右模糊根编码，即可得到当前编码下所有孩子节点
        Wrapper wrapper = new QueryWrapper<SysFunctionRole>().lambda().likeRight(SysFunctionRole::getCode ,rootCode);
        List<SysFunctionRole> list = this.baseMapper.selectList(wrapper);

        List<Integer> idList = new ArrayList<>(list.size());
        list.forEach(x->{
            idList.add(x.getId());
        });

        //删除自身和所有子节点
        removeByIds(idList);

        //删除功能角色映射表中的所有记录
        sysFunctionRoleRelationService.removeByFunctionRoleIds(idList);
    }

    @Override
    public List<SysFunctionRole> getAllParentByCode(List<String> codeList) {
        List<String> parentCodeList = new ArrayList<>(codeList.size());
        NumberCodeGenerator numberCodeGenerator = NumberCodeGenerator.build();
        codeList.forEach(code->{
            String tempCode = numberCodeGenerator.original(code);
            parentCodeList.addAll(numberCodeGenerator.parentCode(tempCode));
        });
        if(parentCodeList.isEmpty()){
            return Collections.EMPTY_LIST;
        }
        return this.baseMapper.selectInCodeList(parentCodeList);
    }

    @Override
    public List<String> getFunctionRoleNameListByUserUuid(String userUuid) {
        List<SysFunctionRole> functionRoleList = this.baseMapper.selectFunctionRoleByUserUuid(userUuid);
        if(functionRoleList.isEmpty()){
            return Collections.EMPTY_LIST;
        }
        //查询角色的所有父角色，子角色拥有父角色的所有权限
        List<String> roleList = new ArrayList<>(functionRoleList.size());
        //整理code
        List<String> codeList = new ArrayList<>(functionRoleList.size());

        functionRoleList.forEach(sysAdminFunctionRole -> {
            //未被禁用角色
            if(sysAdminFunctionRole.isEnable()){
                //添加当前角色
                roleList.add(sysAdminFunctionRole.getName());
                //有父类才添加code并进行查询
                if(sysAdminFunctionRole.getPid() != 0){
                    codeList.add(sysAdminFunctionRole.getCode());
                }
            }
        });
        List<SysFunctionRole> parentList = getAllParentByCode(codeList);
        parentList.forEach(sysAdminFunctionRole -> {
            //未被禁用角色
            if(sysAdminFunctionRole.isEnable()){
                roleList.add(sysAdminFunctionRole.getName());
            }
        });
        return roleList;
    }

    @Override
    public List<ZTreeNode> searchFunctionRoleTreeByUserUuid(String userUuid) {
        List<Integer> functionRoleIdList = sysUserFunctionRoleRelationService.getFunctionRoleIdByUserUuid(userUuid);

        List<SysFunctionRole> list = list();
        List<ZTreeNode> zTreeNodeList = new ArrayList<>(list.size());
        list.forEach(sysAdminFunctionRole -> {
            ZTreeNode zTreeNode = new ZTreeNode();
            zTreeNode.setName(sysAdminFunctionRole.getName()).setId((long)sysAdminFunctionRole.getId()).setPId(0L);
            if(functionRoleIdList.contains(sysAdminFunctionRole.getId())){
                zTreeNode.setChecked(true).setOpen(true);
            }
            zTreeNodeList.add(zTreeNode);
        });

        zTreeNodeList.add(ZTreeNode.createParent());
        return zTreeNodeList;
    }

    private SysFunctionRole selectOneByIdDescLimit1(long id){
        Wrapper wrapper = new QueryWrapper<SysFunctionRole>().lambda().eq(SysFunctionRole::getId ,id)
                .last("ORDER BY id DESC LIMIT 1");
        return this.baseMapper.selectOne(wrapper);
    }

    private SysFunctionRole selectOneByPidDescLimit1(long pid){
        Wrapper wrapper = new QueryWrapper<SysFunctionRole>().lambda().eq(SysFunctionRole::getPid ,pid)
                .last("ORDER BY id DESC LIMIT 1");
        return this.baseMapper.selectOne(wrapper);
    }
}
